Home|Bitmap Help|Printing Forms|Tip Corner|Sprite Byte|Qcard Lesson 4|Do it Right!|Print with LB4.01|Long Filename Lister|Clearing Error Logs|Newsletter help|Index
Sprite Bytes are small tutorials that address a single method to be used with sprites in Liberty BASIC. See Sprite Bytes in previous newsletters for information on user-controls sprites, scrolling backgrounds and shooting. Please see the zipped archive of this newsletter for all files needed to run the demo program.
Sprites Controlled by the Computer
Most games have sprites that are controlled by the computer. These can be bad guys, missiles, obstacles, prizes, treasures, pickups, etc.
Creating an Enemy

An enemy ship!
For this demo, we'll add an enemy ship to the demos from previous Sprite Bytes. We must be concerned with the enemy's location, his speed, his direction of movement, and his boundaries.
Enemy Location
In our demo, the enemy ship will enter from the top of the screen and fly downwards toward the user-controlled ship. He starts with a Y coordinate of 0. The X coordinate can be determined in many ways. If there are several enemy ships, each might always fly at the same X location. It is more usual to have enemies appear in different locations. This can be determined randomly, with the RND() function.
enemyX=int(rnd(0)*maxX)
We could easily start the enemy at the same X location as the ship, too. We do this by retrieving the coordinates of the ship and setting the enemy X equal to the current ship X.
'start enemy at ship location:
#1 "spritexy? ship sx sy"
enemyX=sx
Enemy Speed
The enemy ship travels, so its Y coordinate must change with each frame. The larger the rate of change of the Y coordinate, the faster the enemy ship appears to move.
enemyY=enemyY+5
For each frame, after we've specified new coordinates for the enemy, we use the spritexy command to redraw the enemy ship in its new location.
#1 "spritexy enemy ";enemyX;" ";enemyY
Boundaries
When the enemy ship reaches the bottom of the screen, we reset its coordinates. It starts at the top, so we set its Y coordinate back to 0. We reset its X coordinate in one of the methods described above. The X boundaries are determined either by the location of the user-controlled ship, or by the algorithm in the RND() routine. The user-controlled ship has boundary checking in place, so there is an automatic boundary check when using this method. The RND method uses the maxX setting to determine the maximum X location for the enemy. The routine to move the enemy with each frame looks like this:
[moveEnemy]
enemyY=enemyY+5
'if enemy is at bottom, then move him
'to top and reset X location randomly
if enemyY>maxY then
enemyY=0
'start enemy in random location:
enemyX=int(rnd(0)*maxX)
end if
#1 "spritexy enemy ";enemyX;" ";enemyY
RETURN
Or, it looks like this, depending upon the method chosen to set the X coordinate.
[moveEnemy]
enemyY=enemyY+5
'if enemy is at bottom, then move him
'to top and reset X location randomly
if enemyY>maxY then
enemyY=0
'start enemy at ship location:
#1 "spritexy? ship sx sy"
enemyX=sx
end if
#1 "spritexy enemy ";enemyX;" ";enemyY
RETURN
Direction of Travel
The routines above allow the enemy ship to proceed in a straight line down the screen. We can give the enemy some artificial intelligence quite easily. We do this by checking the X location of the ship with each frame and changing the enemy X coordinate to equal the ship X coordinate.
'move enemy towards ship each frame:
#1 "spritexy? ship sx sy"
enemyX=sx
The entire routine to move the enemy ship then looks like this:
[moveEnemy]
enemyY=enemyY+5
'move enemy towards ship each frame:
#1 "spritexy? ship sx sy"
enemyX=sx
'if enemy is at bottom, then move him
'to top and reset X location randomly
if enemyY>maxY then
enemyY=0
'start enemy at ship location:
#1 "spritexy? ship sx sy"
enemyX=sx
end if
#1 "spritexy enemy ";enemyX;" ";enemyY
RETURN
Collisions!
We have a user-controlled ship, missiles fired by the ship, and an enemy ship. The only problem? Nothing happens when they collide! A future Sprite Byte will discuss collisions. Why wait, though? Why not play with the code and work out some collision handling routines of your own?
DEMO
Please find all of the support files for this program in the zipped archive for this issue.
'move sprite and shoot
'uses spritetravelxy
nomainwin
'ship is 40x40
'shot is 10x10
'enemy is 49x50
maxX=550 : maxY=400
WindowWidth=maxX+50 : WindowHeight=maxY+50
loadbmp "ship","ship.bmp"
loadbmp "shot","shoot.bmp"
loadbmp "enemy","enemy.bmp"
open "Adding an Enemy" for graphics_nsb_nf as #1
#1 "trapclose [quit]"
'create a black background with stars:
#1 "down; fill black; color white"
for i = 1 to 200
x = int(rnd(0)*maxX)
y = int(rnd(0)*maxY)
#1 "set ";x;" ";y
next
#1 "getbmp bkg 0 0 ";maxX;" ";maxY
'set the background
#1 "background bkg"
'add your sprites
#1 "addsprite ship ship"
#1 "addsprite enemy enemy"
'add 10 identical missiles
'all use same loaded bmp
'concatenate sprite names
for i = 1 to 10
#1 "addsprite shot"+str$(i)+" shot"
next
'set ship location
shipX=100 : shipY=maxY-20
#1 "spritexy ship ";shipX;" ";shipY
'set location of all missiles off screen
shotX=-100 : shotY=-100
for i = 1 to 10
#1 "spritexy shot"+str$(i)+" ";shotX;" ";shotY
next
'set location for enemy
enemyX=300 : enemyY=0
#1 "spritexy enemy ";enemyX;" ";enemyY
activeShot=0 'var to hold number of most recently fired missile
bgX=0:bgY=0
'show frame onscreen
#1 "drawsprites"
'set up to trap keypresses
#1 "setfocus; when characterInput [check]"
[mainLoop]
SCAN 'scan for user events
gosub [moveship]
gosub [moveEnemy]
'slight pause to slow action:
calldll #kernel32, "Sleep",10 as long, re as void
goto [mainLoop]
[check]
k$=Inkey$ 'place value of Inkey$ into k$
if k$="4" or asc(right$(k$,1))=37 then gosub [goLeft]
if k$="6" or asc(right$(k$,1))=39 then gosub [goRight]
if k$="8" or asc(right$(k$,1))=38 then gosub [goShoot]
goto [mainLoop]
[goLeft]
#1 "spritexy? ship x y"
if x <= 0 then wait 'ship is at left side already
shipX = shipX - 5
return
[goRight]
#1 "spritexy? ship x y"
if x >= maxX then wait 'ship is at right side already
shipX = shipX + 5
return
[goShoot]
activeShot=activeShot+1
if activeShot>10 then activeShot=1
#1 "spritexy? ship x y"
'start shot near center of ship
shotX=x+15:shotY=maxY
'set shot to travel to top of screen and
'fire event when it gets there
#1 "spritexy shot"+str$(activeShot)+" ";shotX;" ";shotY
#1 "spritetravelxy shot"+str$(activeShot)+" ";shotX;" 0 5 [checkShoot]"
playwave "laser.wav", async
return
[checkShoot]
for i = 1 to 10
#1 "spritexy? shot"+str$(i)+" sx sy"
if sy<=0 then
'move shot sprite off screen, update display
#1 "spritexy shot"+str$(i)+" -100 -100"
end if
next
#1 "drawsprites" 'update screen!
goto [mainLoop]
[moveship]
'put sprites in new location
bgY=bgY-2 'scroll background
#1 "backgroundxy ";bgX;" ";bgY
#1 "spritexy ship ";shipX;" ";shipY
#1 "drawsprites" 'update screen!
RETURN
[moveEnemy]
enemyY=enemyY+5
'move enemy towards ship each frame:
#1 "spritexy? ship sx sy"
enemyX=sx
'if enemy is at bottom, then move him
'to top and reset X location randomly
if enemyY>maxY then
enemyY=0
'start enemy in random location:
'enemyX=int(rnd(0)*maxX)
'start enemy at ship location:
#1 "spritexy? ship sx sy"
enemyX=sx
end if
#1 "spritexy enemy ";enemyX;" ";enemyY
RETURN
[quit]
unloadbmp "bkg"
unloadbmp "ship"
unloadbmp "shot"
close #1:end